﻿#include <windows.h>
#include <iostream>

#pragma comment(lib,"ws2_32.lib") 

int main()
{
	// 0. 初始化网络环境
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		printf("初始化Winsock失败\n");
		return -1;
	}
	printf("初始化Winsock成功\n");
	// 1. 创建服务端句柄（套接字）
	// AF_INET ipv4 AF_INET6 ipv6
	// SOCK_STREAM --> TCP       SOCK_DREAM --> UDP
	SOCKET sockServer = socket(AF_INET, SOCK_STREAM, 0);
	if (INVALID_SOCKET == sockServer)
	{
		printf("创建服务端句柄失败\n");
		WSACleanup();
		return -1;
	}
	printf("1. 创建服务端成功\n");

	// 2. 绑定端口号和IP地址
	SOCKADDR_IN addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(50000);// 端口号  host to net short
	//addr.sin_addr.S_un.S_addr指明了服务端所在的主机位置。
	//addr.sin_addr.S_un.S_addr应当设置为服务端所在的IP地址
	//addr.sin_addr.S_un.S_addr = INADDR_ANY; // IP地址 所有IP都行
	//addr.sin_addr.S_un.S_addr = inet_addr("192.168.1.1"); // 特定IP地址
	addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");   //本机地址
	if (bind(sockServer, (sockaddr*)&addr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
	{
		printf("绑定端口号失败\n");
		closesocket(sockServer);
		WSACleanup();
		return -1;
	}
	printf("2. 绑定端口号成功\n");

	// 3. 监听端口号(告诉操作系统，与当前程序建立逻辑关联)
	if (listen(sockServer, 5) == SOCKET_ERROR)
	{
		printf("监听端口号失败\n");
		closesocket(sockServer);
		WSACleanup();
		return -1;
	}
	printf("3. 监听端口号成功\n");

	while (true)
	{
		// 4. 接收客户端连接 会建立一个新的套接字(他是客户端的标记)
		printf("4. 准备等待客户端到来\n");
		SOCKADDR_IN clientAddr = {};
		int nAddrLen = sizeof(SOCKADDR_IN);
		SOCKET sockClient = accept(sockServer, (sockaddr*)&clientAddr, &nAddrLen);

		if (INVALID_SOCKET == sockClient)
		{
			printf("接收客户端连接失败\n");
			continue; // 错误处理后继续等待下一个客户端
		}
		printf("4. 接收客户端连接成功\n");

		// 与客户端通信的循环
		while (true)
		{
			char szData[1024] = {};
			int ret = recv(sockClient, szData, sizeof(szData) - 1, 0);

			if (ret > 0)
			{
				szData[ret] = '\0'; // 添加字符串结束符
				printf("5. 接收客户端数据成功[%s]\n", szData);

				// 发送回显数据
				ret = send(sockClient, szData, ret, 0);
				if (ret == SOCKET_ERROR)
				{
					printf("发送数据失败\n");
					break; // 发送失败，断开与该客户端的连接
				}
			}
			else if (ret == 0) // 客户端关闭连接
			{
				printf("客户端已主动断开连接。\n");
				break; // 正常退出循环，准备处理下一个客户端
			}
			else // 发生错误
			{
				printf("接收客户端数据失败\n");
				break; // 错误处理后断开连接
			}
		}
		// 关闭客户端套接字
		closesocket(sockClient);
		printf("当前客户端已断开连接，等待下一个客户端...\n");
	}

	// 主循环结束后，关闭服务端套接字
	closesocket(sockServer);
	// 清理Winsock资源
	WSACleanup();
	printf("资源已清理\n");
	return 0;
}